package org.example.model;

import org.javatuples.Pair;

import java.util.*;

public class Dfa {
    private Object Set;
    final int N = 19;
    int[][] m =
    {{3,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
        {3,3,1,0,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
        {3,1,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
        {3,0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
        {3,3,3,3,3,0,1,3,3,3,3,3,3,3,3,3,3,3,2},
        {3,3,3,3,3,3,3,1,3,3,3,3,3,3,3,3,3,3,3},
        {3,3,3,3,3,3,3,0,3,3,3,3,3,3,3,3,3,3,3},
        {3,3,3,3,3,3,3,3,2,3,3,3,3,3,3,3,3,3,3},
        {3,3,3,3,3,3,3,3,3,1,0,2,3,3,3,3,3,3,3},
        {3,3,3,3,3,3,3,3,1,3,3,3,3,3,3,3,3,3,3},
        {3,3,3,3,3,3,3,3,0,3,3,3,3,3,3,3,3,3,3},
        {3,3,3,3,3,3,3,3,3,3,3,3,0,1,3,3,3,3,3},
        {3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,3,3,3,3},
        {3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,3,3},
        {3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,3},
        {3,3,3,3,2,3,3,3,3,3,3,3,3,3,3,3,1,0,3},
        {3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,3,3,3},
        {3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,3},
        {3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3}};
    ArrayList<Set<Integer>> Ti;

    Boolean is_set_the_same(Set<Integer> a, Set<Integer> b)
    {
        return a == b;
    }
    Boolean is_set_in_Ti(Set<Integer> a)
    {
        for(Set<Integer> i:Ti)
        {
            if(is_set_the_same(a, i))
            {
                return true;
            }
        }
        return false;
    }
    Integer find_index(Set<Integer> a)
    {
        int index = 0;
        for(Set<Integer> i:Ti)
        {
            if(is_set_the_same(a, i))
            {
                return index;
            }
            index ++;
        }
        return Ti.size();
    }

    public void Init()
    {

        //count
        // for (int i = 0; i < 54; i ++ ) {
        // 	cout << "T" << i << " [shape=circle]" <<  endl;
        // }

        Set<Integer> start = new HashSet<>();
        // int size = 1;
        start.add(0);
        Ti.add(start);
//	int temp;
        Queue<Pair<Integer,Integer>> search = new LinkedList<>();
        Pair<Integer,Integer> for_Tiptr_each = new Pair<>(0, 1);
        Pair<Integer, Integer> temp = new Pair<Integer, Integer>(0, 0);
        int ptr = 0;
        do
        {
            Set<Integer> out_a = new HashSet<>();
            Set<Integer> out_b = new HashSet<>();
            for(int i: Ti.get(ptr))
            {
                search.add(for_Tiptr_each);
                while(!search.isEmpty())
                {
                    for_Tiptr_each = search.peek();
                    for(int j = 0; j < N ; j ++)
                    {
                        if(m[for_Tiptr_each.getValue0()][j] != 3)
                        {
                            if(for_Tiptr_each.getValue1() == 2)
                            {
                                switch(m[for_Tiptr_each.getValue0()][j])
                                {
                                    case 0:temp.setAt0(j); temp.setAt0(0);
                                            search.add(temp);
                                            out_a.add(j);
                                            break;
                                    case 1:temp.setAt0(j); temp.setAt1(1);
                                            search.add(temp);
                                            out_b.add(j);break;
                                    case 2:temp.setAt0(j); temp.setAt1(2);
                                            search.add(temp);
                                            out_a.add(j);out_b.add(j);break;
                                }
                            }
                            else
                            {
                                switch(m[for_Tiptr_each.getValue0()][j])
                                {
                                    case 2:temp.setAt0(j); temp.setAt1(for_Tiptr_each.getValue1());
                                        search.add(temp);
                                        if (for_Tiptr_each.getValue1() == 0) {
                                            out_a.add(j);
                                        } else {
                                            out_b.add(j);
                                        } break;
                                }
                            }
                        }
                    }
                    search.poll();
                }
            }

            if(!is_set_in_Ti(out_a))
            {
                Ti.add(out_a);
            }
            if(!is_set_in_Ti(out_b))
            {
                Ti.add(out_b);
            }
            String title = "T";
            title += find_index(Ti.get(ptr)).toString();

        }while(ptr != Ti.size());
    }

}
